package com.itcast.myrpc.server;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;

/**
 * @program: bio_tcp
 * @description:
 * @author: zhanghz001
 * @create: 2021-02-22 08:48
 **/
public class MyChannelHandler extends ChannelInboundHandlerAdapter {
    /**
     * 获取客户端发来的数据
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        String msgStr = byteBuf.toString(CharsetUtil.UTF_8);
        System.out.println("客户端传来的数据: " + msgStr);
        
        //1:⼿动释放，就是在使⽤完成后，调⽤ReferenceCountUtil.release(byteBuf); 进⾏释放
        ReferenceCountUtil.release(byteBuf);
        //2:自动释放
        //⼊站的TailHandler、Netty的ChannelPipleline的流⽔线的末端是TailHandler，默认情况下如果每个⼊站处理器Handler都把
        // 消息往下传， TailHandler会释放掉ReferenceCounted类型的消息。
        //将ByteBuf向下传递
        ctx.fireChannelRead(msg);
        
        // 继承SimpleChannelInboundHandler、在SimpleChannelInboundHandler的
        // channelRead()⽅法中，将会进⾏资源的释放，我们的业务代码也需要写⼊到channelRead0()中。
        
        // HeadHandler的出站释放。出站处理⽤到的 Bytebuf 缓冲区，⼀般是要发送的消息，通常由应⽤所申请。在出站流程开始的时候，
        // 通过调⽤ ctx.writeAndFlush(msg)， Bytebuf 缓冲区开始进⼊出站处理的 pipeline 流⽔线 。
        // 在每⼀个出站Handler中的处理完成后，最后消息会来到出站的最后⼀棒 HeadHandler，再经过⼀轮复
        // 杂的调⽤，在flush完成后终将被release掉
        
        ctx.writeAndFlush(Unpooled.copiedBuffer("ok", CharsetUtil.UTF_8));
    }
    
    /**
     * 异常处理,打印异常,关闭channel
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
